/*
 * @Author: AI Assistant
 * @Date: 2024-12-19
 * @Description: 模型管理服务
 */
import { Injectable, Inject, forwardRef } from '@nestjs/common';
import { InjectModel } from 'nest-typegoose';
import { ReturnModelType } from '@typegoose/typegoose';
import { Module as ModuleModel } from '@libs/db/models/module.model';
import { Cube } from '@libs/db/models/cube.model';
import { Templates } from '@libs/db/models/templates.model';
import { WebMenu } from '@libs/db/models/webmenu.model';
import * as fs from 'fs';
import * as path from 'path';
import { createWebComponent, deleteWebComponent, updateWebComponent } from 'utils';
import { ConfigurationService } from '../configuration/configuration.service';
import { WebmenusService } from '../webmenus/webmenus.service';
import { ListDetailService } from '../list-detail/list-detail.service';

@Injectable()
export class WebbaseService {
  constructor(
    @InjectModel(ModuleModel) private readonly moduleModel: ReturnModelType<typeof ModuleModel>,
    @InjectModel(Cube) private readonly cubeModel: ReturnModelType<typeof Cube>,
    @InjectModel(Templates) private readonly templatesModel: ReturnModelType<typeof Templates>,
    @InjectModel(WebMenu) private readonly webMenuModel: ReturnModelType<typeof WebMenu>,
    private configurationService: ConfigurationService,
    @Inject(forwardRef(() => WebmenusService))
    private readonly webmenusService: WebmenusService,
    @Inject(forwardRef(() => ListDetailService))
    private readonly listDetailService: ListDetailService,
  ) { }

  /**
   * 创建模型
   * @param createModuleDto 创建模型的数据
   * @returns 创建的模型数据
   */
  async create(createModuleDto: ModuleModel) {
    // 移除moduleId字段，因为MongoDB会自动生成_id
    const { moduleId, ...createData } = createModuleDto as any;
    const doc = await this.moduleModel.create(createData);
    const savedDoc = await doc.save();
    return {
      ...savedDoc.toObject(),
      moduleId: savedDoc._id
    };
  }

  /**
   * 分页查询模型列表
   * @param query 查询参数
   * @returns 分页数据
   */
  async findAll(query: any) {
    const { moduleName, moduleType, status, pageNum = 1, pageSize = 10 } = query;

    // 构建查询条件
    const matchConditions: any = {};
    if (moduleName) {
      matchConditions.moduleName = { $regex: moduleName, $options: 'i' };
    }
    if (moduleType) {
      matchConditions.moduleType = moduleType;
    }
    if (status !== undefined && status !== '') {
      matchConditions.status = status;
    }

    const result = await this.moduleModel.aggregate([
      {
        $match: matchConditions
      },
      {
        $facet: {
          total: [{ $count: 'count' }],
          rows: [
            { $skip: (pageNum - 1) * pageSize },
            { $limit: pageSize },
            { $sort: { createdAt: -1 } },
            {
              $addFields: {
                moduleId: '$_id'
              }
            }
          ],
        },
      },
      {
        $project: {
          list: '$rows',
          total: { $arrayElemAt: ['$total.count', 0] },
        },
      }
    ]);

    return result[0] || { list: [], total: 0 };
  }

  /**
   * 获取全部模型列表（不带分页）
   * @returns 全部模型列表
   */
  async findAllWithoutPagination() {
    const result = await this.moduleModel.find().sort({ createdAt: -1 }).lean();
    return result.map(item => ({
      ...item,
      moduleId: item._id
    }));
  }

  /**
   * 根据ID查询模型详情
   * @param id 模型ID
   * @returns 模型详情
   */
  async findOne(id: string) {
    const result = await this.moduleModel.findById(id).lean();
    if (result) {
      return {
        ...result,
        moduleId: result._id
      };
    }
    return result;
  }

  /**
   * 更新模型
   * @param id 模型ID
   * @param updateModuleDto 更新数据
   * @returns 更新后的模型数据
   */
  async update(id: string, updateModuleDto: any) {
    // 移除moduleId字段，因为MongoDB使用_id
    const { moduleId, ...updateData } = updateModuleDto;
    const doc = await this.moduleModel.findByIdAndUpdate(
      id,
      updateData,
      { new: true }
    );
    if (doc) {
      return {
        ...doc.toObject(),
        moduleId: doc._id
      };
    }
    return doc;
  }

  /**
   * 删除模型
   * @param id 模型ID
   * @returns 删除结果
   */
  async remove(id: string) {
    return await this.moduleModel.deleteOne({ _id: id });
  }

  /**
   * 批量删除模型
   * @param ids 模型ID数组
   * @returns 删除结果
   */
  async removeMany(ids: string[]) {
    return await this.moduleModel.deleteMany({ _id: { $in: ids } });
  }

  // ==================== Cube 相关方法 ====================

  /**
   * 创建立方体组件
   * @param createCubeDto 立方体组件数据（来源：用户输入）
   * @returns 创建的立方体组件
   */
  async createCube(createCubeDto: Cube) {
    // 如果有组件内容缓存和文件名，先进行重复性检查和文件创建
    if (createCubeDto.bindFileCache && createCubeDto.bindFileName) {
      // 检查数据库中是否已存在相同的bindFileName
      const existingCube = await this.cubeModel.findOne({ bindFileName: createCubeDto.bindFileName });
      if (existingCube) {
        throw new Error(`文件名 '${createCubeDto.bindFileName}' 已存在，请使用不同的文件名`);
      }

      // 尝试创建对应的组件文件
      const systemConfig = await this.configurationService.getSystemConfig();
      const siteTemplate = systemConfig.siteInfo.siteTemplate;
      const result = createWebComponent(createCubeDto.bindFileCache, createCubeDto.bindFileName, siteTemplate);
      if (!result.status) {
        throw new Error(`创建组件文件失败: ${result.msg}`);
      }
    }

    // 组件文件创建成功后，再将数据保存到数据库
    const doc = await this.cubeModel.create(createCubeDto);
    return doc.toObject();
  }

  /**
   * 分页查询立方体组件列表
   * @param query 查询参数（来源：用户输入）
   * @returns 分页数据
   */
  async findAllCubes(query: any) {
    const { name, type, pageNum = 1, pageSize = 10 } = query;

    // 构建查询条件
    const matchConditions: any = {};
    if (name) {
      matchConditions.name = { $regex: name, $options: 'i' };
    }
    if (type) {
      matchConditions.type = type;
    }

    const result = await this.cubeModel.aggregate([
      {
        $match: matchConditions
      },
      {
        $facet: {
          total: [{ $count: 'count' }],
          rows: [
            { $skip: (pageNum - 1) * pageSize },
            { $limit: pageSize },
            { $sort: { createdAt: -1 } }
          ],
        },
      },
      {
        $project: {
          list: '$rows',
          total: { $arrayElemAt: ['$total.count', 0] },
        },
      }
    ]);

    return result[0] || { list: [], total: 0 };
  }

  /**
   * 获取全部立方体组件列表（不带分页）
   * @returns 全部立方体组件列表
   */
  async findAllCubesWithoutPagination() {
    return await this.cubeModel.find().sort({ createdAt: -1 }).lean();
  }

  /**
   * 根据ID查询立方体组件详情
   * @param id 立方体组件ID（来源：用户输入）
   * @returns 立方体组件详情
   */
  async findOneCube(id: string) {
    return await this.cubeModel.findById(id).lean();
  }

  /**
   * 更新立方体组件
   * @param id 立方体组件ID（来源：用户输入）
   * @param updateCubeDto 更新数据（来源：用户输入）
   * @returns 更新后的立方体组件数据
   */
  async updateCube(id: string, updateCubeDto: any) {
    return await this.cubeModel.findByIdAndUpdate(
      id,
      updateCubeDto,
      { new: true }
    );
  }

  /**
   * 删除立方体组件
   * @param id 立方体组件ID（来源：用户输入）
   * @returns 删除结果
   */
  async removeCube(id: string) {
    const cubeDetail = await this.findOneCube(id);
    if (cubeDetail.bindFileName) {
      const systemConfig = await this.configurationService.getSystemConfig();
      const siteTemplate = systemConfig.siteInfo.siteTemplate;
      const deleteRes = deleteWebComponent(cubeDetail.bindFileName, siteTemplate);
      if (!deleteRes.status) {
        throw new Error(`删除组件文件失败: ${deleteRes.msg}`);
      }
      return await this.cubeModel.deleteOne({ _id: id });
    } else {
      throw new Error(`立方体组件 ${id} 没有关联的组件文件`);
    }
  }

  /**
   * 批量删除立方体组件
   * @param ids 立方体组件ID数组（来源：用户输入）
   * @returns 删除结果
   */
  async removeManyCubes(ids: string[]) {
    return await this.cubeModel.deleteMany({ _id: { $in: ids } });
  }

  // ==================== Templates 相关方法 ====================

  /**
   * 创建新的 Templates
   * @param createTemplatesDto - 创建 Templates 的数据（来源：请求体）
   * @returns 创建的 Templates
   */
  async createTemplates(createTemplatesDto: Partial<Templates>) {
    try {
      const existingTemplates = await this.templatesModel.findOne({ bindFileName: createTemplatesDto.bindFileName });
      if (existingTemplates) {
        throw new Error(`文件名 '${createTemplatesDto.bindFileName}' 已存在，请使用不同的文件名`);
      }
      // 尝试创建对应的组件文件
      const systemConfig = await this.configurationService.getSystemConfig();
      const siteTemplate = systemConfig.siteInfo.siteTemplate;
      const result = createWebComponent(createTemplatesDto.templateContentCache, createTemplatesDto.bindFileName, siteTemplate);
      if (!result.status) {
        throw new Error(`创建组件文件失败: ${result.msg}`);
      }
      const doc = await this.templatesModel.create(createTemplatesDto);
      return doc.toObject;
    } catch (error) {
      throw new Error(`创建 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 查找所有 Templates（支持分页和条件查询）
   * @param page - 页码（来源：查询参数）
   * @param limit - 每页数量（来源：查询参数）
   * @param templateName - 模板名称过滤（来源：查询参数）
   * @param type - 类型过滤（来源：查询参数）
   * @returns Templates 列表和分页信息
   */
  async findAllTemplates(page: number = 1, limit: number = 10, templateName?: string, type?: string) {
    try {
      const query: any = {};

      if (templateName) {
        query.templateName = { $regex: templateName, $options: 'i' };
      }

      if (type) {
        query.type = type;
      }

      const skip = (page - 1) * limit;
      const [templates, total] = await Promise.all([
        this.templatesModel.find(query).skip(skip).limit(limit).sort({ createdAt: -1 }),
        this.templatesModel.countDocuments(query),
      ]);

      return {
        rows: templates,
        total,
      };
    } catch (error) {
      throw new Error(`查询 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 查找所有 Templates（不分页）
   * @param templateName - 模板名称过滤（来源：查询参数）
   * @param type - 类型过滤（来源：查询参数）
   * @returns Templates 列表
   */
  async findAllTemplatesWithoutPagination(templateName?: string, type?: string) {
    try {
      const query: any = {};

      if (templateName) {
        query.templateName = { $regex: templateName, $options: 'i' };
      }

      if (type) {
        query.type = type;
      }

      const templates = await this.templatesModel.find(query).sort({ createdAt: -1 });
      return templates;
    } catch (error) {
      throw new Error(`查询 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 根据 ID 查找单个 Templates
   * @param id - Templates ID（来源：路径参数）
   * @returns Templates 详情
   */
  async findOneTemplates(id: string) {
    try {
      const templates = await this.templatesModel.findById(id);
      if (!templates) {
        throw new Error('Templates 不存在');
      }
      return templates;
    } catch (error) {
      throw new Error(`查询 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 更新 Templates
   * @param id - Templates ID（来源：路径参数）
   * @param updateTemplatesDto - 更新数据（来源：请求体）
   * @returns 更新后的 Templates
   */
  async updateTemplates(id: string, updateTemplatesDto: Partial<Templates>) {
    try {
      console.log(updateTemplatesDto.bindFileName, 'updateTemplatesDto');

      // 先获取原始模板数据
      const originalTemplate = await this.templatesModel.findById(id);
      if (!originalTemplate) {
        throw new Error('Templates 不存在');
      }

      // 获取系统配置中的站点模板
      const systemConfig = await this.configurationService.getSystemConfig();
      const siteTemplate = systemConfig.siteInfo.siteTemplate;

      // 检查是否需要更新文件名
      const isFileNameChanged = updateTemplatesDto.bindFileName &&
        updateTemplatesDto.bindFileName !== originalTemplate.bindFileName;

      // 检查是否需要更新文件内容
      const isContentChanged = updateTemplatesDto.templateContentCache !== undefined &&
        updateTemplatesDto.templateContentCache !== originalTemplate.templateContentCache;

      // 如果文件名发生变化，需要先检查新文件名是否已存在
      if (isFileNameChanged) {
        const existingTemplate = await this.templatesModel.findOne({
          bindFileName: updateTemplatesDto.bindFileName,
          _id: { $ne: id } // 排除当前模板
        });
        if (existingTemplate) {
          throw new Error(`文件名 '${updateTemplatesDto.bindFileName}' 已存在，请使用不同的文件名`);
        }
      }

      const updateResult = updateWebComponent(
        updateTemplatesDto.templateContentCache,
        originalTemplate.bindFileName,
        siteTemplate
      );
      if (!updateResult.status) {
        throw new Error(`更新组件文件失败: ${updateResult.msg}`);
      }

      // 更新数据库记录
      const templates = await this.templatesModel.findByIdAndUpdate(
        id,
        updateTemplatesDto,
        { new: true, runValidators: true }
      );

      return templates;
    } catch (error) {
      throw new Error(`更新 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 删除 Templates
   * @param id - Templates ID（来源：路径参数）
   * @returns 删除结果
   */
  async removeTemplates(id: string) {
    try {
      // 检查是否有菜单正在使用此模板
      const menuUsingTemplate = await this.webMenuModel.findOne({ detailTplId: id });
      if (menuUsingTemplate) {
        throw new Error('该模板正在被菜单使用，无法删除');
      }

      const templates = await this.templatesModel.findByIdAndDelete(id);
      if (!templates) {
        throw new Error('Templates 不存在');
      }
      if (templates.bindFileName) {
        const systemConfig = await this.configurationService.getSystemConfig();
        const siteTemplate = systemConfig.siteInfo.siteTemplate;
        const deleteRes = deleteWebComponent(templates.bindFileName, siteTemplate);
        if (!deleteRes.status) {
          throw new Error(`删除组件文件失败: ${deleteRes.msg}`);
        }
      }
      return { success: true, message: 'Templates 删除成功' };
    } catch (error) {
      throw new Error(`删除 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 批量删除多个 Templates
   * @param ids - Templates ID 数组（来源：请求参数）
   * @returns 删除结果
   */
  async removeManyTemplates(ids: string[]) {
    try {
      const result = await this.templatesModel.deleteMany({ _id: { $in: ids } });
      return {
        success: true,
        deletedCount: result.deletedCount,
        message: `成功删除 ${result.deletedCount} 个 Templates`,
      };
    } catch (error) {
      throw new Error(`批量删除 Templates 失败: ${error.message}`);
    }
  }

  /**
   * 读取默认模块模板文件内容
   * @returns 模板文件内容
   */
  async getDefaultModuleTemplate() {
    try {
      const filePath = path.join(process.cwd(), 'WebPageTemplate', 'modules', 'defaultModule.txt');
      const content = fs.readFileSync(filePath, 'utf8');
      return { content };
    } catch (error) {
      throw new Error(`读取模板文件失败: ${error.message}`);
    }
  }

  /**
   * 根据模板ID获取模板内容缓存
   * @param tplId 模板ID（来源：用户输入）
   * @returns 模板内容缓存
   */
  async getTemplateContentCache(tplId: string): Promise<string> {
    try {
      const template = await this.findOneTemplates(tplId);
      return template?.templateContentCache || '';
    } catch (error) {
      throw new Error(`获取模板内容缓存失败: ${error.message}`);
    }
  }

  /**
   * 获取非category类型菜单对应的列表详情数据
   * @returns 包含菜单信息和对应列表详情的数据
   */
  async getMenusWithListDetails() {
    try {
      // 1. 调用webmenus服务获取菜单树
      const menuTree = await this.webmenusService.getMenuTree();

      // 2. 遍历第一层菜单，筛选modelType不为category的数据
      const nonCategoryMenus = menuTree.filter(menu => menu.modelType !== 'category');

      // 3. 为每个非category菜单获取对应的列表详情数据
      const result = [];

      for (const menu of nonCategoryMenus) {
        if (menu.modelId) {
          try {
            // 调用list-detail服务的findAllWithFilters方法
            const listDetails = await this.listDetailService.findAllWithRecommendSort({
              moduleId: menu.modelId,
              isPublished: true, // 只获取已发布的数据
              pageNum: 1,
              pageSize: 15 // 最多只显示15条
            });

            result.push({
              menu: {
                id: menu._id,
                name: menu.name,
                code: menu.code,
                modelId: menu.modelId,
                modelType: menu.modelType,
                description: menu.description,
                link: menu.link,
                icon: menu.icon,
                sort: menu.sort
              },
              listDetails: listDetails.rows,
              total: listDetails.total
            });
          } catch (error) {
            console.error(`获取菜单 ${menu.name} 对应的列表详情失败:`, error.message);
            // 即使某个菜单的数据获取失败，也继续处理其他菜单
            result.push({
              menu: {
                id: menu._id,
                name: menu.name,
                code: menu.code,
                modelId: menu.modelId,
                modelType: menu.modelType,
                description: menu.description,
                link: menu.link,
                icon: menu.icon,
                sort: menu.sort
              },
              listDetails: [],
              total: 0,
              error: error.message
            });
          }
        }
      }

      return result;
    } catch (error) {
      throw new Error(`获取菜单和列表详情数据失败: ${error.message}`);
    }
  }
}

